package com.lagou.sqlSession;

import com.lagou.config.SqlType;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.util.List;

public class DefaultSqlSession implements SqlSession{
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {

        // 将要完成对Executor里面的query进行调用
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        List<Object> query = simpleExecutor.query(configuration, mappedStatement, params);

        return (List<E>) query;
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        List<Object> objects = selectList(statementId, params);
        if(objects.size() == 1){
            return (T) objects.get(0);
        }else {
            throw  new RuntimeException("返回结果过多");
        }
    }

    @Override
    public boolean updateById(MappedStatement mappedStatement, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        boolean update = simpleExecutor.update(configuration, mappedStatement, params);
        return update;
    }

    @Override
    public boolean deleteById(MappedStatement mappedStatement, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        boolean delete = simpleExecutor.delete(configuration, mappedStatement, params);
        return delete;
    }

    @Override
    public boolean insert(MappedStatement mappedStatement, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        boolean insert = simpleExecutor.insert(configuration, mappedStatement, params);
        return insert;
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                // selectOne
                String methodName = method.getName();
                // className:namespace
                String className = method.getDeclaringClass().getName();

                //statementId:namespace.methodName
                String key = className + "." + methodName;

                Type genericReturnType = method.getGenericReturnType();

                // 1、判断是要增加、查询、修改、删除
                // 2、需要通过格式化方法进行判断
                // 3、获取mappedStatement：获取sql类型
                MappedStatement mappedStatement = configuration.getMappedStatementMap().get(key);
                SqlType sqlType = mappedStatement.getSqlType();

                // 通过MappedSatement获取sqlType:用来'判断是什么操作类型
                if(sqlType.equals(SqlType.UPDATE)){
                    return updateById(mappedStatement, args);
                }
                if(sqlType.equals(SqlType.INSERT)){
                    return insert(mappedStatement,args);
                }
                if(sqlType.equals(SqlType.DELETE)){
                    return deleteById(mappedStatement, args);
                }

                if (genericReturnType instanceof ParameterizedType) {
                    return selectList(key, args);
                }
                return selectOne(key, args);
            }
        });
        return (T) o;
    }

}
